﻿/*global jQuery, document */

var OnlineOS = (function (jQuery, document, window) {
	'use strict';

	// global object
	var oos = { };
	// static functions dictionary
	var sfn = oos.sfn = { };
	// object functions dictionary
	var fn = oos.fn = { };
	// constructor functions dictionary
	var ctor = oos.ctor = { };

	var defaultErrorFunc = sfn.defaultErrorFunc = function() {
		alert('Error!');
	};
	var serverRequestId = 0;
	// send a server request
	var serverRequest = sfn.serverRequest = function(data, success, error) {
		if(!error)
			error = defaultErrorFunc;
		data.format = 'json';
		data.requestId = serverRequestId;
		serverRequestId++;
		jQuery.ajax({
			url: location.href,
			data: data,
			type: 'POST',
			success: success,
			error: error
		});
	};

	// send a server command
	var serverCommand = sfn.serverCommand = function(command, data, success, error) {
		data.command = command;
		serverRequest(data, success, error);
	};


	// function called when the browser window is resized
	var browserWindowResize = sfn.browserWindowResize = function () {
		var jqWindow = jQuery(window);
		var screen = oos.screen;
		if(screen && screen.resize)
			screen.resize(jqWindow.width(), jqWindow.height());
	};

	// create drag drop event functions for control moving
	var createDragDrop = sfn.createDragDrop = function (element) {
		var startMouse, startElement;
		var jqElement = jQuery(element);
		var jqWindow = jQuery(window);
		var mouseDownFunc = function (e) {
			startMouse = {
				left: e.pageX,
				top: e.pageY
			};
			startElement = {
				left: jqElement.offset().left,
				top: jqElement.offset().top
			};
			jqWindow.mouseup(mouseUpFunc);
			jqWindow.mousemove(mouseMoveFunc);
		};
		var mouseUpFunc = function (e) {
			jqWindow.unbind('mouseup', mouseUpFunc);
			jqWindow.unbind('mousemove', mouseMoveFunc);
		};
		var mouseMoveFunc = function (e) {
			var dx = e.pageX - startMouse.left;
			var dy = e.pageY - startMouse.top;
			jqElement.offset({left: startElement.left + dx, top: startElement.top + dy});
		};
		return {
			start: mouseDownFunc,
			end: mouseUpFunc,
			drag: mouseMoveFunc
		};
	};

	// create drag drop event functions for control resizing
	var createResizeDragDrop = sfn.createResizeDragDrop = function (element, distance, cornerDistance) {
		var jqElement = jQuery(element);
		var jqWindow = jQuery(window);
		var jqBody = jQuery(document.body);
		var startElement, startMouse;
		var currentlyResizable = false;
		var resizing = false;
		var resizedSide = null;

		var elementMoveFunc = function (e) {
			if(resizing || jqElement.hasClass('maximized'))
				return;
			var state = {
				left: jqElement.offset().left,
				top: jqElement.offset().top,
				width: jqElement.outerWidth(),
				height: jqElement.outerHeight()
			};
			var borderDistances = {
				top: e.pageY - state.top,
				left: e.pageX - state.left,
				bottom: state.top + state.height - e.pageY,
				right: state.left + state.width - e.pageX
			};
			currentlyResizable = true;
			if(borderDistances.top <= cornerDistance && borderDistances.left <= cornerDistance) {
				jqBody.css('cursor', 'nw-resize');
				resizedSide = 'nw'
			} else if(borderDistances.bottom <= cornerDistance && borderDistances.left <= cornerDistance) {
				jqBody.css('cursor', 'ne-resize');
				resizedSide = 'sw';
			} else if(borderDistances.top <= cornerDistance && borderDistances.right <= cornerDistance) {
				jqBody.css('cursor', 'sw-resize');
				resizedSide = 'ne';
			} else if(borderDistances.bottom <= cornerDistance && borderDistances.right <= cornerDistance) {
				jqBody.css('cursor', 'se-resize');
				resizedSide = 'se';
			} else if(borderDistances.top <= distance) {
				jqBody.css('cursor', 'n-resize');
				resizedSide = 'n';
			} else if(borderDistances.left <= distance) {
				jqBody.css('cursor', 'w-resize');
				resizedSide = 'w';
			} else if(borderDistances.right <= distance) {
				jqBody.css('cursor', 'e-resize');
				resizedSide = 'e';
			} else if(borderDistances.bottom <= distance) {
				jqBody.css('cursor', 's-resize');
				resizedSide = 's';
			} else {
				jqBody.css('cursor', '');
				currentlyResizable = false
				resizedSide = null;
			}
		};
		var mouseLeaveFunc = function (e) {
			if(resizing)
				return;
			jqBody.css('cursor', '');
		};
		var mouseDownFunc = function (e) {
			if(!currentlyResizable)
				return;
			resizing = true;
			startMouse = {
				left: e.pageX,
				top: e.pageY
			};
			startElement = {
				left: jqElement.offset().left,
				top: jqElement.offset().top,
				width: jqElement.width(),
				height: jqElement.height()
			};
			jqWindow.mouseup(mouseUpFunc);
			jqWindow.mousemove(mouseMoveFunc);
		};
		var mouseUpFunc = function (e) {
			resizing = false;
			jqWindow.unbind('mouseup', mouseUpFunc);
			jqWindow.unbind('mousemove', mouseMoveFunc);
		};
		var mouseMoveFunc = function (e) {
			if(!(resizing && resizedSide) || jqElement.hasClass('maximized'))
				return;
			var dx = e.pageX - startMouse.left;
			var dy = e.pageY - startMouse.top;
			if(resizedSide === 'n') {
				jqElement.offset({left: startElement.left, top: startElement.top + dy}).height(startElement.height - dy);
			} else if(resizedSide === 's') {
				jqElement.height(startElement.height + dy);
			} else if(resizedSide === 'w') {
				jqElement.offset({left: startElement.left + dx, top: startElement.top}).width(startElement.width - dx);
			} else if(resizedSide === 'e') {
				jqElement.width(startElement.width + dx);
			} else if(resizedSide === 'sw') {
				jqElement.offset({left: startElement.left + dx, top: startElement.top}).width(startElement.width - dx).height(startElement.height + dy);
			} else if(resizedSide === 'nw') {
				jqElement.offset({left: startElement.left + dx, top: startElement.top + dy}).width(startElement.width - dx).height(startElement.height - dy);
			} else if(resizedSide === 'se') {
				jqElement.height(startElement.height + dy).width(startElement.width + dx);
			} else if(resizedSide === 'ne') {
				jqElement.offset({left: startElement.left, top: startElement.top + dy}).height(startElement.height - dy).width(startElement.width + dx);
			}
			jqElement.resize();
		};
		return {
			move: elementMoveFunc,
			start: mouseDownFunc,
			end: mouseUpFunc,
			leave: mouseLeaveFunc
		};
	};

	var bindMouseImages = sfn.bindMouseImages = function (element, img, imgHover) {
		var jqElement = jQuery(element);
		jqElement.mouseenter(function () {
			if(jqElement.attr('src') === img) {
				jqElement.attr('src', imgHover);
			}
		});
		jqElement.mouseleave(function () {
			if(jqElement.attr('src') === imgHover) {
				jqElement.attr('src', img);
			}
		});
	};

	var Screen = ctor.Screen = function () {
		var screen = oos.screen = { };
		var jqScreen = jQuery('<div class="screen"></div>');
		var jqDesktop = jQuery('<div class="desktop"></div>');
		var jqTaskBar = jQuery('<div class="taskBar"></div>');
		var jqStartButton = jQuery('<div class="button startButton"><img class="icon" src="/Images/html5-icon.png" alt="" /><span class="text">Démarrer</span></div>')
		var jqProgramBar = jQuery('<div class="programBar"></div>');
		var jqBody = jQuery(document.body);
		var startMenu = StartMenu();
		var windows = [];
		var focused = null;

		var toggleStartMenu = function (e) {
			jqStartButton.toggleClass('down');
			startMenu.toggle();
		};

		screen.element = jqDesktop[0];

		jqTaskBar.append(jqStartButton);
		jqTaskBar.append(jqProgramBar);
		jqScreen.append(jqDesktop);
		jqScreen.append(startMenu.element);
		jqScreen.append(jqTaskBar);
		jqBody.append(jqScreen);

		jQuery(window).resize(browserWindowResize);
		jqProgramBar.mousedown(function (e) {
			e.stopPropagation();
			if(e.target === this) {
				setFocus(null);
				screen.hideStartMenu();
			}
		});
		jqScreen.mousedown(function (e) {
			setFocus(null);
		});
		jqDesktop.mousedown(function (e) {
			screen.hideStartMenu();
		});
		jqTaskBar.mousedown(function (e) {
			if(e.target === this) {
				screen.hideStartMenu();
			}
		});
		jqStartButton.mousedown(toggleStartMenu);

		screen.showStartMenu = function () {
			jqStartButton.addClass('down');
			startMenu.show();
		};
		screen.hideStartMenu = function () {
			jqStartButton.removeClass('down');
			startMenu.hide();
		};
		screen.toggleStartMenu = toggleStartMenu;
		screen.resize = function (w, h) {
			if(w)
				jqScreen.width(w);
			if(h)
				jqScreen.height(h);
			
			var i = 0;
			for(;i<windows.length;i++)
				windows[i].parentResized();

			jqProgramBar.width(jqTaskBar.width() - jqStartButton.outerWidth(true));
		};
		screen.addWindow = function (params) {
			if(!params)
				params = { };
			if(!params.ctor)
				params.ctor = Window;
			params.parent = screen;
			var window = params.ctor(params);
			jQuery(window.element).css('z-index', windows.length);
			jqDesktop.append(window.element);
			if(window.programBarButtonElement)
				jqProgramBar.append(window.programBarButtonElement);
			window.setContentHeight();
			windows.push(window);
			setFocus(window);
			
			return window;
		};
		var decrementZIndexesAbove = function (zIndex) {
			var i = 0;
			for(;i<windows.length;i++) {
				if(windows[i] !== window) {
					var jqWindow = jQuery(windows[i].element);
					var z = parseInt(jqWindow.css('z-index'));
					if(z >= zIndex && z > 0) {
						jqWindow.css('z-index', z - 1);
					}
				}
			}
		};
		screen.removeWindow = function (window) {
			var windowIndex = windows.indexOf(window);
			if(windowIndex > -1) {
				var zIndex = parseInt(jQuery(window.element).css('z-index'));
				windows.splice(windowIndex, 1);
				decrementZIndexesAbove(zIndex);
			}
		};
		var setFocus = screen.setFocus = function (focusable) {
			if(focused !== focusable) {
				if(focused && focused.unfocus)
					focused.unfocus();
				focused = focusable;
				if(focusable && jqStartButton.hasClass('down'))
					screen.hideStartMenu();
				if(focusable && focusable.focus) {
					if(focusable.element) {
						var zIndex = parseInt(jQuery(focusable.element).css('z-index'));
						decrementZIndexesAbove(zIndex);
						jQuery(focusable.element).css('z-index', windows.length - 1);
					}
					focusable.focus();
				}
			}
		};

		browserWindowResize();

		return screen;
	};

	var StartMenu = ctor.StartMenu = function (params) {
		var startMenu = { };
		var jqStartMenu = jQuery('<div class="startMenu"></div>');
		var jqTop = jQuery('<div class="top"></div>');
		var jqLeft = jQuery('<div class="left"></div>');
		var jqRight = jQuery('<div class="right"></div>');
		var jqBottom = jQuery('<div class="bottom"></div>');
		var jqRightTop = jQuery('<div class="top"></div>');
		var jqIcon = jQuery('<img class="icon" src="/Images/html5-icon.png" alt="" />');
		var jqLeftList = jQuery('<ol></ol>');
		var jqRightList = jQuery('<ol></ol>');
		var jqSearch = jQuery('<input class="search" placeholder="Rechercher les programmes et fichiers" />');
		var jqSearchImg = jQuery('<img class="search" src="/Images/Icons/OOS/search.png" />');
		var jqStopButton = jQuery('<div class="button stop">Arrêter</div>');

		bindMouseImages(jqSearchImg[0], '/Images/Icons/OOS/search.png', '/Images/Icons/OOS/search.hover.png');

		jqStartMenu.append(jqTop);
		jqStartMenu.append(jqBottom);
		jqTop.append(jqLeft);
		jqTop.append(jqRight);
		jqRight.append(jqRightTop);
		jqRight.append(jqRightList);
		jqLeft.append(jqLeftList);
		jqRightTop.append(jqIcon);
		jqBottom.append(jqSearch);
		jqBottom.append(jqSearchImg);
		jqBottom.append(jqStopButton);

		startMenu.element = jqStartMenu[0];

		startMenu.show = function () { jqStartMenu.show(); }
		startMenu.hide = function () { jqStartMenu.hide(); }
		startMenu.toggle = function () { jqStartMenu.toggle(); }

		return startMenu;
	};

	var Window = ctor.Window = function (params) {
		var window = { };
		var windowedState;
		var iconSrc = '/Images/html5-icon.png';
		if(params && params.icon)
			iconSrc = params.icon
		var jqWindow = jQuery('<div class="window"></div>');
		var jqTitleBar = jQuery('<div class="titleBar"></div>');
		var jqTitleBarIcon = jQuery('<img class="icon" src="' + iconSrc + '" alt="" />');
		var jqTitleBarCaption = jQuery('<span class="caption">Window</span>');
		var jqContent = jQuery('<div class="content"></div>');
		var jqTitleBarActions = jQuery('<div class="actions"></div>');
		var jqTitleBarMinimize = jQuery('<div class="button minimize"><img class="icon" src="/Images/Icons/OOS/minimize.png" alt="_" /></div>');
		var jqTitleBarMaximize = jQuery('<div class="button maximize"><img class="icon" src="/Images/Icons/OOS/maximize.png" alt="+" /></div>');
		var jqTitleBarClose = jQuery('<div class="button close"><img class="icon" src="/Images/Icons/OOS/close.png" alt="X" /></div>');
		var jqTaskBarButton = jQuery('<div class="button" title="Window"><img class="icon" src="' + iconSrc + '" alt="" /></div>');
		var dragDrop = createDragDrop(jqWindow[0]);
		var resizer = createResizeDragDrop(jqWindow[0], 4, 8);

		if(params) {
			if(params.caption) {
				jqTitleBarCaption.text(params.caption);
				jqTaskBarButton.attr('title', params.caption);
			}
			if(params.width)
				jqWindow.width(params.width);
			if(params.height)
				jqWindow.height(params.height);
			if(params.parent)
				window.parent = params.parent;
		}

		var setContentHeight = window.setContentHeight = function () {
			var height = jqWindow.height();
			if(jqTitleBar.is(':visible'))
				height -= jqTitleBar.outerHeight();
			jqContent.height(height);
			if(window.contentResized)
				window.contentResized(jqContent.width(), jqContent.height());
		};

		window.element = jqWindow[0];
		window.programBarButtonElement = jqTaskBarButton[0];
		window.contentElement = jqContent[0];

		jqTitleBarActions.append(jqTitleBarMinimize);
		jqTitleBarActions.append(jqTitleBarMaximize);
		jqTitleBarActions.append(jqTitleBarClose);
		jqTitleBar.append(jqTitleBarIcon);
		jqTitleBar.append(jqTitleBarCaption);
		jqTitleBar.append(jqTitleBarActions);
		jqWindow.append(jqTitleBar);
		jqWindow.append(jqContent);

		jqWindow.mousemove(resizer.move).mouseenter(resizer.move).mouseleave(resizer.leave);
		jqWindow.resize(setContentHeight);
		jqWindow.mousedown(function (e) {
			e.stopPropagation();
			resizer.start(e);
			window.focus();
		});
		jqTaskBarButton.click(function (e) {
			e.stopPropagation();
			if(!jqWindow.hasClass('focus')) {
				jqWindow.show();
				window.focus();
			} else {
				jqWindow.hide();
				window.unfocus();
			}
			return false;
		});
		jqTitleBarMaximize.click(function (e) {
			e.stopPropagation();
			toggleMaximize();
		});
		jqTitleBar.dblclick(function (e) {
			toggleMaximize();
		});
		jqTitleBar.mousedown(dragDrop.start);

		window.maximize = function () {
			if(!jqWindow.hasClass('maximized'))
				this.toggleMaximize();
		};
		var parentResized = window.parentResized = function () {
			if(jqWindow.hasClass('maximized')) {
				var jqParent = jqWindow.parent();
				this.resize(jqParent.width(), jqParent.height());
			}
		};
		var toggleMaximize = window.toggleMaximize = function () {
			var jqParent = jqWindow.parent();
			if(!jqWindow.hasClass('maximized')) {
				windowedState = {
					left: jqWindow.offset().left,
					top: jqWindow.offset().top,
					width: jqWindow.width(),
					height: jqWindow.height()
				};
				jqWindow.addClass('maximized');
				jqWindow.css('left', 0).css('top', 0);
				window.resize(jqParent.width(), jqParent.height());
				jqTitleBarMaximize.find('img.icon').attr('src', '/Images/Icons/OOS/windowed.png').attr('alt', '-');
			} else {
				jqWindow.removeClass('maximized');
				jqWindow.offset({left: windowedState.left, top: windowedState.top});
				window.resize(windowedState.width, windowedState.height);
				jqTitleBarMaximize.find('img.icon').attr('src', '/Images/Icons/OOS/maximize.png').attr('alt', '+');
			}
			return this;
		};
		window.center = function () {
			if(!jqWindow.hasClass('maximized')) {
				var jqParent = jqWindow.parent();
				var parentOffset = jqParent.offset();
				var offset = {
					left: parentOffset.left + (jqParent.width() - jqWindow.outerWidth()) / 2,
					top: parentOffset.top + (jqParent.height() - jqWindow.outerHeight()) / 2
				};
				jqWindow.offset(offset);
			}
			return this;
		};
		window.resize = function (w, h) {
			if(w)
				jqWindow.width(w);
			if(h) {
				jqWindow.height(h);
				setContentHeight();
			}
			return this;
		};
		window.focus = function () {
			if(!jqWindow.hasClass('focus')) {
				jqTaskBarButton.addClass('down');
				jqWindow.addClass('focus');
				if(this.parent && this.parent.setFocus)
					this.parent.setFocus(this);
			}
			return this;
		};
		window.unfocus = function () {
			if(jqWindow.hasClass('focus')) {
				jqTaskBarButton.removeClass('down');
				jqWindow.removeClass('focus');
			}
			return this;
		};
		return window;
	};

	var ExplorerWindow = ctor.ExplorerWindow = function (params) {
		if(!params)
			params = { };
		if(!params.caption)
			params.caption = 'Explorer';
		var currentPath = null;
		var window = Window(params);
		var jqContent = jQuery(window.contentElement);
		var jqTopContent = jQuery('<div class="top"></div>');
		var jqMainContent = jQuery('<div class="main"></div>');
		var jqBottomContent = jQuery('<div class="bottom"></div>');
		var jqLeftContent = jQuery('<div class="left"></div>');
		var jqRightContent = jQuery('<div class="right"></div>');
		var jqNavigationBar = jQuery('<div class="navigationBar"></div>');
		var jqPreviousImg = jQuery('<img class="previous" src="/Images/Icons/OOS/previous.off.png" alt="Précédent" title="Précédent" />');
		var jqNextImg = jQuery('<img class="next" src="/Images/Icons/OOS/next.off.png" alt="Suivant" title="Suivant" />');
		var jqLocation = jQuery('<div class="location"></div>');
		var jqLocationInput = jQuery('<input class="location" />');
		var jqLocationList = jQuery('<ol class="location"></ol>');
		var jqRefreshImg = jQuery('<img class="refresh" src="/Images/Icons/OOS/refresh.png" alt="Actualiser" title="Actualiser" />')
		var jqSearch = jQuery('<div class="search"></div>');
		var jqSearchInput = jQuery('<input class="search" placeholder="Rechercher dans :" />');
		var jqSearchImg = jQuery('<img class="search" src="/Images/Icons/OOS/search.png" alt="" />');

		bindMouseImages(jqRefreshImg[0], '/Images/Icons/OOS/refresh.png', '/Images/Icons/OOS/refresh.hover.png');
		bindMouseImages(jqSearchImg[0], '/Images/Icons/OOS/search.png', '/Images/Icons/OOS/search.hover.png');
		bindMouseImages(jqNextImg[0], '/Images/Icons/OOS/next.png', '/Images/Icons/OOS/next.hover.png');
		bindMouseImages(jqPreviousImg[0], '/Images/Icons/OOS/previous.png', '/Images/Icons/OOS/previous.hover.png');

		//var listView = ListView();
		var listView = TableView();
		var hierarchyView = HierarchyView();

		jqLeftContent.append(hierarchyView.element);
		jqRightContent.append(listView.element);

		jQuery(window.element).addClass('explorer');

		jqLocation.append(jqLocationInput);
		jqLocation.append(jqLocationList);
		jqLocation.append(jqRefreshImg);
		jqSearch.append(jqSearchInput);
		jqSearch.append(jqSearchImg);
		jqNavigationBar.append(jqPreviousImg);
		jqNavigationBar.append(jqNextImg);
		jqNavigationBar.append(jqLocation);
		jqNavigationBar.append(jqSearch);
		jqTopContent.append(jqNavigationBar);
		jqMainContent.append(jqLeftContent);
		jqMainContent.append(jqRightContent);
		jqContent.append(jqTopContent);
		jqContent.append(jqMainContent);
		jqContent.append(jqBottomContent);

		window.contentResized = function (w, h) {
			var height = h - jqTopContent.outerHeight(true) - jqBottomContent.outerHeight(true);
			jqMainContent.height(height);
			var width = w - jqLeftContent.outerWidth(true);
			jqRightContent.width(width);
			listView.resize(width, height);
		};

		var buildLocationPath = function (path) {
			var pathMap = path.split('\\');
			var currentPath = '';
			var i = 0;
			jqLocationList.html('');
			jqLocationInput.val(path);
			var onClickItem = function (e) {
				var path = jQuery(this).data('path');
				if(path)
					window.setPath(path);
			};
			for(;i<pathMap.length;i++) {
				if(pathMap[i]) {
					currentPath += pathMap[i];
					if(i === 0)
						currentPath += '\\';
					var innerHtml = '<span class="text">' + pathMap[i] + '</span>';
					if(i + 1 < pathMap.length)
						innerHtml += '<img class="expand" alt="" src="/Images/Icons/OOS/expand.png" />';
					var jqItem = jQuery('<li class="icon">' + innerHtml + '</li>');
					jqItem.data('path', currentPath);
					jqItem.click(onClickItem);
					if(i !== 0)
						currentPath += '\\';
					jqLocationList.append(jqItem);
				}
			}
		};

		jqLocationList.click(function (e) {
			if(e.target === this) {
				jqLocationList.hide();
				jqLocationInput.show().focus().select();
			}
		});
		jqLocationInput.blur(function () {
			jqLocationInput.hide();
			jqLocationList.show();
			if(jqLocationInput.val() !== currentPath) {
				window.setPath(jqLocationInput.val());
				jqLocationInput.val(currentPath);
			}
		});
		
		var dblClickFolder = function () {
			var jqThis = jQuery(this);
			var item = jqThis.data('item');
			window.setPath(item.path);
		};

		jqPreviousImg.click(function () {
			if(historyIndex - 1 >= 0) {
				historyIndex--;
				window.setPath(history[historyIndex], true);
			}
		});
		jqNextImg.click(function () {
			if(history.length > historyIndex + 1) {
				historyIndex++;
				window.setPath(history[historyIndex], true);
			}
		});

		var history = [];
		var historyIndex = -1;
		window.setPath = function (path, doNotChangeHistory) {
			var request = {
				path: path
			};
			serverCommand('listDirectory', request, function (data) {
				if(data.requestId === request.requestId && data.directory) {
					listView.clear();
					currentPath = path;
					if(!doNotChangeHistory) {
						historyIndex ++;
						history.length = historyIndex;
						history[historyIndex] = path;
					}
					if(!history || history.length <= 1) {
						jqNextImg.attr('src','/Images/Icons/OOS/next.off.png').attr('title', 'Suivant');
						jqPreviousImg.attr('src','/Images/Icons/OOS/previous.off.png').attr('title', 'Précédent');
					} else if(history.length > historyIndex && historyIndex >= 0) {
						if(history.length > historyIndex + 1)
							jqNextImg.attr('src','/Images/Icons/OOS/next.png').attr('title', 'Avancer à ' + history[historyIndex + 1]);
						else
							jqNextImg.attr('src','/Images/Icons/OOS/next.off.png').attr('title', 'Suivant');
						if(historyIndex > 0)
							jqPreviousImg.attr('src','/Images/Icons/OOS/previous.png').attr('title', 'Retour à ' + history[historyIndex - 1]);
						else
							jqPreviousImg.attr('src','/Images/Icons/OOS/previous.off.png').attr('title', 'Précédent');
					}
					var i = 0;
					var array = data.directory.children;
					buildLocationPath(path);
					jqLocationInput.val(path);
					jqSearchInput.attr('placeholder', 'Rechercher dans : ' + path);
					for(;i<array.length;i++) {
						array[i].path = (path + '\\' + array[i].name).replace('\\\\', '\\');
						var item = listView.addItem(array[i]);
						if(array[i].directory) {
							var jqItem = jQuery(item.element);
							jqItem.dblclick(dblClickFolder);
						}
					}
				}
			});
		};

		window.setPath('C:\\');
		
		var createHierarchyInnerList = function () {
			var that = this;
			var path = jQuery(this.element).data('item').path;
			var request = {
				path: path,
				directoryOnly: true,
				countChildrenDirectory:  true
			};
			serverCommand('listDirectory', request, function (data) {
				if(data.requestId === request.requestId && data.directory) {
					var i = 0;
					var item;
					var array = data.directory.children;
					for(;i<array.length;i++) {
						array[i].path = (path + '\\' + array[i].name).replace('\\\\', '\\');
						item = that.addItem(array[i]);
						item.createInnerList = createHierarchyInnerList;
					}
				}
			});
		};

		var request = {
			path: 'C:\\',
			directoryOnly: true,
			countChildrenDirectory:  true
		};
		serverCommand('listDirectory', request, function (data) {
			if(data.requestId === request.requestId && data.directory) {
				var i = 0;
				var item;
				var array = data.directory.children;
				for(;i<array.length;i++) {
					array[i].path = 'C:\\' + array[i].name;
					item = hierarchyView.addItem(array[i]);
					item.createInnerList = createHierarchyInnerList;
				}
			}
		});

		return window;
	};

	var TableView = ctor.TableView = function (params) {

		if(!params)
			params = { };
		if(!params.columns)
			params.columns = [
				{id:'name', label:'Nom', width:275},
				{id:'modified', label:'Modifié le', width:120},
				{id:'type', label:'Type', width:120},
				{id:'size', label:'Taille', width:80}
			];
			
		var selecteds = [ ];
		var columns = params.columns;
		var tableView = { };
		var jqTableView = jQuery('<div class="tableView"></div>');
		var jqTable = jQuery('<table class="icons"></table>');
		var jqColgroup = jQuery('<colgroup></colgroup>');
		var jqTableHeader = jQuery('<thead></thead>');
		var jqTableBody = jQuery('<tbody></tbody>');


		var jqTrHeader = jQuery('<tr class="header"></tr>');
		var jqHeaders = [];
		var jqCols = [];
		// used in loop
		var i=0;
		var totalWidth = 0;
		var jqHeader, jqCol;
		var jqBody = jQuery(document.body);
		for(;i<columns.length;i++) {
			jqHeader = jQuery('<th class="' + columns[i].id + '">' + (columns[i].label || '')  + '</th>');
			jqCol = jQuery('<col class="' + columns[i].id + '" />');
			jqHeaders.push(jqHeader);
			jqCols.push(jqCol);
			if(columns[i].width) {
				totalWidth += columns[i].width;
				jqCol.css('width', columns[i].width);
			}
			jqColgroup.append(jqCol);
			jqTrHeader.append(jqHeader);
		}
		var jqFillerCol = jQuery('<col class="filler" />');
		var jqFillerHeader = jQuery('<th class="filler"></th>');
		jqColgroup.append(jqFillerCol);
		jqTrHeader.append(jqFillerHeader);

		jqTableHeader.append(jqTrHeader);
		jqTable.append(jqColgroup);
		jqTable.append(jqTableHeader);
		jqTable.append(jqTableBody);

		var jqTableClone = jqTable.clone();
		var clonedCols = jqTableClone.find('col');
		var jqDivHeader = jQuery('<div class="header"></div>');
		jqDivHeader.append(jqTableClone);
		
		jqTableView.append(jqDivHeader);
		jqTableView.append(jqTable);

		jqTableView.scroll(function (e) {
			jqDivHeader.css('top', jqTableView.scrollTop() + 'px');
		});

		tableView.element = jqTableView[0];
		
		tableView.resize = function (w, h) {
			jqTableView.hide();
			jqTableView.width(w).height(h);
			jqTableView.show();
		};
		
		tableView.clear = function () {
			jqTableBody.html('');
		};
		tableView.addItem = function (item) {
			var tableItem = { };
			var jqTr = jQuery('<tr class="icon"></tr>');
			var i = 0;
			for(;i<columns.length;i++) {
				var jqTd = jQuery('<td class="' + columns[i].id + '"></td>');
				jqTd.text((item[columns[i].id] || ''));
				if(columns[i].id === 'name') {
					var jqIcon = jQuery('<img class="icon" src="/Images/html5-icon.png" alt="" />');
					if(item.icon)
						jqIcon.attr('src', item.icon);
					jqTd.prepend(jqIcon);
				}
				jqTr.append(jqTd);
			}
			jqTr.data('item', item);
			jqTableBody.append(jqTr);

			tableItem.element = jqTr[0];
			
			jqTr.mousedown(function () {
				var i = 0;
				var jqThis = jQuery(this);
				for(;i<selecteds.length;i++)
					selecteds[i].removeClass('selected');
				selecteds.length = 0;
				selecteds.push(jqThis);
				jqThis.addClass('selected');
			});

			return tableItem;
		};

		return tableView;
	};

	var ListView = ctor.ListView = function (params) {
		var selecteds = [ ];
		var listView = { };
		var jqListview = jQuery('<div class="listView"></div>');
		var jqList = jQuery('<ol class="icons"></ol>');

		jqListview.append(jqList);

		listView.element = jqListview[0];

		listView.resize = function (w, h) {
			jqListview.hide();
			jqListview.width(w).height(h);
			jqListview.show();
		};
		listView.clear = function () {
			jqList.html('');
		};
		listView.addItem = function (item) {
			var listItem = { };
			var jqItem = jQuery('<li class="icon"></li>');
			var jqIcon = jQuery('<img class="icon" src="/Images/html5-icon.png" alt="" />');
			var jqName = jQuery('<span class="text">' + item.name + '</span>');
			jqItem.data('item', item);
			if(item.icon)
				jqIcon.attr('src', item.icon);

			jqItem.append(jqIcon);
			jqItem.append(jqName);

			jqList.append(jqItem);

			listItem.element = jqItem[0];

			jqItem.mousedown(function () {
				var i = 0;
				var jqThis = jQuery(this);
				for(;i<selecteds.length;i++)
					selecteds[i].removeClass('selected');
				selecteds.length = 0;
				selecteds.push(jqThis);
				jqThis.addClass('selected');
			});

			return listItem;
		};

		return listView;
	};

	var HierarchyView = ctor.HierarchyView = function (params) {
		var selecteds = [ ];
		var hierarchyView = { }
		var jqHierarchyView = jQuery('<div class="hierarchyView"></div>');
		var jqList = jQuery('<ol class="icons"></ol>');

		jqHierarchyView.append(jqList);

		hierarchyView.element = jqHierarchyView[0];

		var createItem = function (item) {
			var listItem = { };
			var jqItem = jQuery('<li class="icon"></li>');
			var jqExpando = jQuery('<img class="expando" src="/Images/Icons/OOS/plus.png" alt="" />');
			var jqIcon = jQuery('<img class="icon" src="/Images/html5-icon.png" alt="" />');
			var jqName = jQuery('<span class="text">' + item.name + '</span>');

			jqItem.data('item', item);
			if(item.icon)
				jqIcon.attr('src', item.icon);

			jqItem.append(jqExpando);
			jqItem.append(jqIcon);
			jqItem.append(jqName);

			jqItem.mousedown(function (e) {
				e.stopPropagation();
				var i = 0;
				var jqThis = jQuery(this);
				for(;i<selecteds.length;i++)
					selecteds[i].removeClass('selected');
				selecteds.length = 0;
				selecteds.push(jqThis);
				jqThis.addClass('selected');
			});

			if(item.hasChildrenDirectory) {
				jqExpando.click(function () {
					if(jqItem.hasClass('open')) {
						jqItem.removeClass('open');
						jqExpando.attr('src', '/Images/Icons/OOS/plus.png');
					} else {
						jqItem.addClass('open');
						jqExpando.attr('src', '/Images/Icons/OOS/minus.png');
						if(!listItem.innerList && listItem.createInnerList)
							listItem.createInnerList();
					}
				});
			} else
				jqExpando.css('visibility', 'hidden');

			listItem.element = jqItem[0];
			listItem.addItem = addInnerItem;

			return listItem;
		};
		var addInnerItem = function (item) {
			var jqInnerList;
			if(!this.innerList) {
				jqInnerList = jQuery('<ol></ol>');
				jqInnerList.appendTo(this.element);
				this.innerList = jqInnerList[0];
			} else
				jqInnerList = jQuery(this.innerList);
				
			var innerItem = createItem(item);
			jqInnerList.append(innerItem.element);
			return innerItem;
		};
		hierarchyView.addItem = function (item) {
			var item = createItem(item);
			jqList.append(item.element);
			return item;
		};

		return hierarchyView;
	};

	jQuery(document).ready(function () {
		oos.screen = Screen();
		oos.screen.addWindow({ctor: ExplorerWindow});
		oos.screen.addWindow().center();
	});

	return oos;

}(jQuery, document, window));
